package com.qyl.http_upload.client;

import com.qyl.http_upload.constant.ContentTypeEnum;

import java.io.*;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;

public class HttpClient {


    /**
     * post multipart/form-data
     * */
    public static void sendPostFormDataWithImgFile(HttpSendPostVo vo) throws Exception {
        // socket客户端连接本机的tomcat服务器，端口为8080
        Socket socket = new Socket(vo.getIp(), vo.getPort());
        OutputStream out = socket.getOutputStream();
        String boundary = "qinyulin";
        File file = new File("D:\\1668245082534.png");
        FileInputStream fin = new FileInputStream(file);
        byte[] fileBytes = fin.readAllBytes();
        StringBuffer fileBefore = new StringBuffer();
        fileBefore.append(getFormItem("\"id\"", "11", boundary));
        fileBefore.append(getFormItem("\"name\"", "11", boundary));
        fileBefore.append("--"+boundary+"\r\n");
        fileBefore.append("Content-Disposition: form-data; name=\"file\"; filename=\""+file.getName()+"\"\r\n");
        fileBefore.append("Content-Type: "+Files.probeContentType(file.toPath()));
        fileBefore.append("Connection: Keep-Alive\r\n");
        fileBefore.append("\r\n");
        System.out.println(fileBefore);
        String end = "--"+boundary+"--";
        StringBuffer sb = new StringBuffer();
        sb.append("POST " + vo.getUrl() + " HTTP/1.1\r\n");
        sb.append("Host: " + vo.getIp() + "\r\n");
        sb.append("Content-Type: "+ContentTypeEnum.FORM_DATA.getContentType()+";boundary="+boundary +"\r\n");
       int length = fileBefore.toString().getBytes().length
                + fileBytes.length + end.getBytes().length;
        sb.append("Content-Length: " + length + " \r\n");
//        sb.append("Content-Length: 21397 \r\n");
//        sb.append("Accept:text/html, application/xhtml+xml, */*").append("\r\n");
        sb.append("accept-encoding: gzip, deflate, br");
        sb.append("\r\n");
        sb.append("\r\n");
        System.out.println("**************** Server request ****************");
        out.write(sb.toString().getBytes());
        // 下面是数据
        out.write(fileBefore.toString().getBytes());
        out.write(fileBytes);
//        byte b[]=new byte[1024];
//        int rb = 0;
//        while((rb = fin.read(b))!=-1){
//            out.write(b,0,rb);
//        };
        out.write("\r\n".getBytes(StandardCharsets.UTF_8));
        out.write(end.getBytes(StandardCharsets.UTF_8));
        // socket客户端接收tomcat返回的数据
//        BufferedReader inReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//        // 以下是服务器返回的数据
//        System.out.println("**************** Server response ****************");
//        String tmp = "";
//        while ((tmp = inReader.readLine()) != null) {
//            // 解析服务器返回的数据，做相应的处理
//            System.out.println(tmp);
//        }
        fin.close();
        out.close();
//        inReader.close();
    }

    /**
     * post multipart/form-data
     * */
    public static void sendPostFormDataWithFile(HttpSendPostVo vo) throws Exception {
        String boundary = "qinyulin";
        StringBuffer data = new StringBuffer();
        data.append(getFormItem("\"id\"", "11", boundary));
        data.append(getFormItem("\"name\"", "11", boundary));
        data.append(getFormFileItem("\"file\"", "D:\\text.txt",boundary));
        data.append("--"+boundary+"--");

        StringBuffer sb = new StringBuffer();
        sb.append("POST " + vo.getUrl() + " HTTP/1.1\r\n");
        sb.append("Host: " + vo.getIp() + "\r\n");
        sb.append("Content-Type: "+ContentTypeEnum.FORM_DATA.getContentType()+";boundary="+boundary +"\r\n");
        sb.append("Content-Length: " + data.length() + "\r\n");
        sb.append("Connection: Close\r\n");
        sb.append("\r\n");
        sb.append(data);
        sb.append("\r\n");
//        System.out.println(sb);
        sendHttp(vo, sb.toString());
    }

    /**
     * post multipart/form-data
     * */
    public static void sendPostFormDataNoFile(HttpSendPostVo vo) throws IOException {
        String boundary = "qinyulin";
        StringBuffer data = new StringBuffer();
        data.append(getFormItem("id", "11", boundary));
        data.append(getFormItem("name", "11", boundary));
        data.append("--"+boundary+"--");

        StringBuffer sb = new StringBuffer();
        sb.append("POST " + vo.getUrl() + " HTTP/1.1\r\n");
        sb.append("Host: " + vo.getIp() + "\r\n");
        sb.append("Content-Type: "+ContentTypeEnum.FORM_DATA.getContentType()+";boundary="+boundary +"\r\n");
        sb.append("Content-Length: " + data.length() + "\r\n");
        sb.append("Connection: Close\r\n");
        sb.append("\r\n");
        sb.append(data);
        sb.append("\r\n");
        sendHttp(vo, sb.toString());
    }

    private static String getFormItem(String name, String value, String boundary){
        StringBuffer sb = new StringBuffer();
        sb.append("--"+boundary+"\r\n");
        sb.append("Content-Disposition: form-data; name="+name);
        sb.append("\r\n");
        sb.append("\r\n");
        sb.append(value);
        sb.append("\r\n");
        return sb.toString();
    }

    private static String getFormFileItem(String name, String filePath, String boundary) throws Exception {
        File file = new File(filePath);
        StringBuffer sb = new StringBuffer();
        sb.append("--"+boundary+"\r\n");
        sb.append("Content-Disposition: form-data; name="+name+"; filename=\""+file.getName()+"\"\r\n");
        sb.append("Content-Type: text/plain");
        sb.append("\r\n");
        sb.append("\r\n");
        String line = null;
        BufferedReader reader = new BufferedReader(new FileReader(file));
        while ((line = reader.readLine()) != null){
            sb.append(line + "\r\n");
        }
//        sb.append("\r\n");
        return sb.toString();
    }

    public static byte[] getBytesByFile(File file) throws IOException {
        FileInputStream fis = null;
        ByteArrayOutputStream bos = new ByteArrayOutputStream(1000);
        try {
            fis = new FileInputStream(file);
            byte[] b = new byte[1000];
            int n;
            while ((n = fis.read(b)) != -1) {
                bos.write(b, 0, n);
            }
            byte[] data = bos.toByteArray();
            return data;
        } catch (Exception e) {
        } finally {
            if (fis != null){
                fis.close();
            }
            bos.close();
        }
        return null;
    }



    /**
     * post application/x-www-from-urlencoded
     **************** Server request ****************
     POST /file/text HTTP/1.1
     Host: 127.0.0.1
     Content-Length: 22
     Content-Type: application/x-www-form-urlencoded
     Connection: Close

     name=gloomyfish&age=32

     **************** Server response ****************
     HTTP/1.1 200
     Content-Type: application/json
     Transfer-Encoding: chunked
     Date: Sat, 12 Nov 2022 05:11:14 GMT
     Connection: close

     11
     {"msg":"success"}
     0

     Disconnected from the target VM, address: '127.0.0.1:63070', transport: 'socket'

     Process finished with exit code 0

     * */
    public static void sendPost(HttpSendPostVo vo) throws IOException {

        String data = URLEncoder.encode("name", "utf-8") + "="
                + URLEncoder.encode("哈哈哈哈", "utf-8")
                + "&" + URLEncoder.encode("age", "utf-8") + "="
                + URLEncoder.encode("32", "utf-8");
        StringBuffer sb = new StringBuffer();
        sb.append("POST " + vo.getUrl() + " HTTP/1.1\r\n");
        sb.append("Host: " + vo.getIp() + "\r\n");
        sb.append("Content-Length: " + data.length() + "\r\n");
        sb.append("Content-Type: "+ContentTypeEnum.FORM_URLENCODED.getContentType()+"\n");
        sb.append("Connection: Close\r\n");
        sb.append("\r\n"); // \r\n和 \n都可以
        sb.append(data);
        sb.append("\r\n");
        sendHttp(vo, sb.toString());
    }


    /**
     * 模拟的数据
     * */
        private static String sendData(){
        return """
POST /file/text HTTP/1.1
Host: 127.0.0.1
Content-Length: 22
Content-Type: application/x-www-form-urlencoded
Connection: Close

name=gloomyfish&age=32
 """;
    }

    private static String sendData2(){
        return """
POST /file/text HTTP/1.1
Host: 127.0.0.1
Content-Type: multipart/form-data; boundary=ss
Content-Length: 113
Connection: Close

--ss
Content-Disposition: form-data; name="id"

111
--ss
Content-Disposition: form-data; name="name"

222
--ss--
""";
    }

    private void compareStr(StringBuffer sb){
        String s = sendData();
        String s2 = sb.toString();
        for(int i = 0; i < s.length(); i ++){
            char c = s.charAt(i);
            char c2= s2.charAt(i);
            System.out.println(c+"   "+c2+"    "+i);
            if(c != c2){
                System.out.println("不同：：  "+c+"   "+c2+"    "+i);
            }
        }
        System.out.println( sendData().toString());
        System.out.println(sb.toString()+ "    "+sb.length());
        System.out.println(sb.toString().equals(sendData().toString()));
    }


    public void sendPost2() throws IOException {
//        String path = "/file/text";
//        String data = URLEncoder.encode("name", "utf-8") + "=" + URLEncoder.encode("gloomyfish", "utf-8") + "&" +
//                URLEncoder.encode("age", "utf-8") + "=" + URLEncoder.encode("32", "utf-8");
//        // String data = "name=zhigang_jia";
//        SocketAddress dest = new InetSocketAddress("127.0.0.1", 8080);
//        socket.connect(dest);
//        OutputStreamWriter streamWriter = new OutputStreamWriter(socket.getOutputStream(), "utf-8");
//        bufferedWriter = new BufferedWriter(streamWriter);
//        StringBuffer sb = new StringBuffer();
//        sb.append("POST " + path + " HTTP/1.1\r\n");
//        sb.append("Host: " + this.host + "\r\n");
//        sb.append("Content-Length: " + data.length() + "\r\n");
//        sb.append("Content-Type: application/x-www-form-urlencoded\r\n");
//        sb.append("Connection: Close\r\n");
//        sb.append("\r\n");
//        sb.append(data);
//        sb.append("\r\n");
//        sb = new StringBuffer();
//        sb.append(sendData());
//        System.out.println(sb);
//
//        System.out.println("........................");
//        bufferedWriter.write(sb.toString());
//        bufferedWriter.flush();
//
//        BufferedInputStream streamReader = new BufferedInputStream(socket.getInputStream());
//        bufferedReader = new BufferedReader(new InputStreamReader(streamReader, "utf-8"));
//        String line = null;
//        while ((line = bufferedReader.readLine()) != null) {
//            System.out.println(line);
//        }
//        bufferedReader.close();
//        bufferedWriter.close();
//        socket.close();
    }


    /**
     * GET requestParam
     * 报文：
     * GET /file/get?name=111 HTTP/1.1
     * Host: 127.0.0.1:8080
     * Connection: Close
     *
     *
     * HTTP/1.1 200
     * Content-Type: text/plain;charset=UTF-8
     * Content-Length: 3
     * Date: Sat, 12 Nov 2022 05:01:50 GMT
     * Connection: close
     *
     * 111
     * */
    public static void sendGet(HttpSendGetVo vo) {
        try {
            StringBuffer httpBody = new StringBuffer(200);
            httpBody.append("GET "+vo.getUrl()+"?"+vo.getParams()+" HTTP/1.1\r\n");
            httpBody.append("Host: "+vo.getIp()+":"+vo.getPort()+"\r\n"); // 这个也是必须加的
//            httpBody.append("Accept: text/html\r\n");
            httpBody.append("Connection: Close\r\n"); // 这个必须加，否则不关闭
            httpBody.append("\r\n");
            httpBody.append("");
            sendHttp(vo, httpBody.toString());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void sendHttp(HttpSendVo vo, String httpBody){
        try {
            System.out.println("**************** Server request ****************");
            System.out.println(httpBody);
            // socket客户端连接本机的tomcat服务器，端口为8080
            Socket socket = new Socket(vo.getIp(), vo.getPort());
//            socket.setSoTimeout(30000);

            // socket客户端发送登录请求
            PrintWriter outWriter = new PrintWriter(socket.getOutputStream());
            outWriter.println(httpBody);

            outWriter.flush();

            // socket客户端接收tomcat返回的数据
            BufferedReader inReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            // 以下是服务器返回的数据
            System.out.println("**************** Server response ****************");
            String tmp = "";
            while ((tmp = inReader.readLine()) != null) {
                // 解析服务器返回的数据，做相应的处理
                System.out.println(tmp);
            }
            outWriter.close();
            inReader.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws Exception {
//        File file = new File("D:\\1668234106017.jpg");
//        String mimeType = Files.probeContentType(file.toPath());
//        System.out.println(mimeType);
//        sendGet(new HttpSendGetVo("/file/get", "127.0.0.1", 8080, "name=111"));
//        sendPostFormDataNoFile(new HttpSendPostVo("/file/text", "127.0.0.1", 8080, ""));
//        sendPostFormDataWithFile(new HttpSendPostVo("/file/text", "127.0.0.1", 8080, ""));
        sendPostFormDataWithImgFile(new HttpSendPostVo("/file/text", "127.0.0.1", 8080, null));
    }

}
